import 'dart:ffi';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'esc_command.dart';
import 'flutter_gprinter.dart';
import 'flutter_gprinter_platform_interface.dart';

/// An implementation of [FlutterGprinterPlatform] that uses method channels.
class MethodChannelFlutterGprinter extends FlutterGprinterPlatform {
  /// The method channel used to interact with the native platform.
  @visibleForTesting
  final methodChannel = const MethodChannel('flutter_gprinter');
  var _handlers = [];

  MethodChannelFlutterGprinter() {
    methodChannel.setMethodCallHandler((call) async {
      switch (call.method) {
        case "connect":
          for (var element in _handlers) {
            element(call.arguments);
          }
          break;
      }
      return null;
    });
  }

  @override
  Future<String?> getPlatformVersion() async {
    final version =
        await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }

  @override
  void addMethodCallHandler(CallHandler handler) {
    _handlers.add(handler);
  }

  @override
  void navUsbDevices() {
    methodChannel.invokeMethod("navUsbDevices");
  }

  @override
  void navBTDevices() {
    methodChannel.invokeMethod("navBTDevices");
  }

  @override
  void navWifiDevices() {
    methodChannel.invokeMethod("navWifiDevices");
  }

  @override
  void autoConnect() {
    methodChannel.invokeMethod("autoConnect");
  }

  @override
  void connectUSB(String pathName) {
    methodChannel.invokeMethod("connectUSB", {"pathName": pathName});
  }

  @override
  void connectNet(String ipAddress) {
    methodChannel.invokeMethod("connectNet", {"ipAddress": ipAddress});
  }

  @override
  void connectBt(String macAddress) {
    methodChannel.invokeMethod("connectBt", {"macAddress": macAddress});
  }

  @override
  void disconnect() {
    methodChannel.invokeMethod("disconnect");
  }

  Future<bool> write(List<int> bytes) async{
    await methodChannel.invokeMethod<bool>("write", {
      "bytes": bytes
    });
    return true;
  }
}
